home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Graphics Programming (2nd Edition) / Visual Basic Graphics Programming 2nd Edition.iso / Src / Ch10 / Mand.frm (.txt) < prev    next >
Encoding:
Visual Basic Form  |  1999-06-09  |  14.4 KB  |  463 lines

  1. VERSION 5.00
  2. Object = "{F9043C88-F6F2-101A-A3C9-08002B2F49FB}#1.2#0"; "COMDLG32.OCX"
  3. Begin VB.Form frmMand 
  4.    Caption         =   "Mand"
  5.    ClientHeight    =   3810
  6.    ClientLeft      =   2370
  7.    ClientTop       =   1320
  8.    ClientWidth     =   3810
  9.    LinkTopic       =   "Form1"
  10.    PaletteMode     =   1  'UseZOrder
  11.    ScaleHeight     =   254
  12.    ScaleMode       =   3  'Pixel
  13.    ScaleWidth      =   254
  14.    Begin MSComDlg.CommonDialog dlgFile 
  15.       Left            =   120
  16.       Top             =   120
  17.       _ExtentX        =   847
  18.       _ExtentY        =   847
  19.       _Version        =   393216
  20.    End
  21.    Begin VB.PictureBox picCanvas 
  22.       AutoRedraw      =   -1  'True
  23.       BackColor       =   &H00000000&
  24.       Height          =   3810
  25.       Left            =   0
  26.       MousePointer    =   2  'Cross
  27.       ScaleHeight     =   250
  28.       ScaleMode       =   3  'Pixel
  29.       ScaleWidth      =   250
  30.       TabIndex        =   0
  31.       Top             =   0
  32.       Width           =   3810
  33.    End
  34.    Begin VB.Menu mnuFile 
  35.       Caption         =   "&File"
  36.       Begin VB.Menu mnuFileSaveAs 
  37.          Caption         =   "&Save As..."
  38.          Shortcut        =   ^A
  39.       End
  40.    End
  41.    Begin VB.Menu mnuScaleMnu 
  42.       Caption         =   "&Scale"
  43.       Begin VB.Menu mnuScale 
  44.          Caption         =   "x&2"
  45.          Index           =   2
  46.       End
  47.       Begin VB.Menu mnuScale 
  48.          Caption         =   "x&4"
  49.          Index           =   4
  50.       End
  51.       Begin VB.Menu mnuScale 
  52.          Caption         =   "x&8"
  53.          Index           =   8
  54.       End
  55.       Begin VB.Menu mnuScaleFull 
  56.          Caption         =   "&Full Scale"
  57.       End
  58.    End
  59.    Begin VB.Menu mnuOpt 
  60.       Caption         =   "&Options"
  61.       Begin VB.Menu mnuOptOptions 
  62.          Caption         =   "&Set Options"
  63.       End
  64.    End
  65.    Begin VB.Menu mnuMovie 
  66.       Caption         =   "&Movie"
  67.       Begin VB.Menu mnuMovieCreate 
  68.          Caption         =   "&Create Movie..."
  69.       End
  70.    End
  71. Attribute VB_Name = "frmMand"
  72. Attribute VB_GlobalNameSpace = False
  73. Attribute VB_Creatable = False
  74. Attribute VB_PredeclaredId = True
  75. Attribute VB_Exposed = False
  76. Option Explicit
  77. Private m_DrawingBox As Boolean
  78. Private m_StartX As Single
  79. Private m_StartY As Single
  80. Private m_CurX As Single
  81. Private m_CurY As Single
  82. Private m_Xmin As Single
  83. Private m_Xmax As Single
  84. Private m_Ymin As Single
  85. Private m_Ymax As Single
  86. Public MaxIterations As Integer
  87. Public NumColors As Integer
  88. Private m_Colors() As Long
  89. Private Const MIN_X = -2.2
  90. Private Const MAX_X = 1
  91. Private Const MIN_Y = -1.2
  92. Private Const MAX_Y = 1.2
  93. ' Return this color's value.
  94. Property Get Color(ByVal Index As Integer) As Long
  95.     Color = m_Colors(Index)
  96. End Property
  97. ' Add this color to the list.
  98. Public Sub AddColor(ByVal new_color As Long)
  99.     NumColors = NumColors + 1
  100.     ReDim Preserve m_Colors(1 To NumColors)
  101.     m_Colors(NumColors) = new_color
  102. End Sub
  103. ' Adjust the aspect ratio of the selected
  104. ' coordinates so they fit the window properly.
  105. Private Sub AdjustAspect()
  106. Dim want_aspect As Single
  107. Dim picCanvas_aspect As Single
  108. Dim hgt As Single
  109. Dim wid As Single
  110. Dim mid As Single
  111.     want_aspect = (m_Ymax - m_Ymin) / (m_Xmax - m_Xmin)
  112.     picCanvas_aspect = picCanvas.ScaleHeight / picCanvas.ScaleWidth
  113.     If want_aspect > picCanvas_aspect Then
  114.         ' The selected area is too tall and thin.
  115.         ' Make it wider.
  116.         wid = (m_Ymax - m_Ymin) / picCanvas_aspect
  117.         mid = (m_Xmin + m_Xmax) / 2
  118.         m_Xmin = mid - wid / 2
  119.         m_Xmax = mid + wid / 2
  120.     Else
  121.         ' The selected area is too short and wide.
  122.         ' Make it taller.
  123.         hgt = (m_Xmax - m_Xmin) * picCanvas_aspect
  124.         mid = (m_Ymin + m_Ymax) / 2
  125.         m_Ymin = mid - hgt / 2
  126.         m_Ymax = mid + hgt / 2
  127.     End If
  128. End Sub
  129. ' Draw the Mandelbrot set.
  130. Private Sub DrawMandelbrot()
  131. ' Work until the magnitude squared > 4.
  132. Const MAX_MAG_SQUARED = 4
  133. Dim pixels() As RGBTriplet
  134. Dim bits_per_pixel As Integer
  135. Dim wid As Long
  136. Dim hgt As Long
  137. Dim clr As Long
  138. Dim i As Integer
  139. Dim j As Integer
  140. Dim ReaC As Double
  141. Dim ImaC As Double
  142. Dim dReaC As Double
  143. Dim dImaC As Double
  144. Dim ReaZ As Double
  145. Dim ImaZ As Double
  146. Dim ReaZ2 As Double
  147. Dim ImaZ2 As Double
  148. Dim r As Integer
  149. Dim b As Integer
  150. Dim g As Integer
  151.     picCanvas.Line (0, 0)-(picCanvas.ScaleWidth, picCanvas.ScaleHeight), vbBlack, BF
  152.     DoEvents
  153.     ' Get the image's pixels.
  154.     GetBitmapPixels picCanvas, pixels, bits_per_pixel
  155.     ' Adjust the coordinate bounds to fit picCanvas.
  156.     AdjustAspect
  157.     ' dReaC is the change in the real part
  158.     ' (X value) for C. dImaC is the change in the
  159.     ' imaginary part (Y value).
  160.     wid = picCanvas.ScaleWidth
  161.     hgt = picCanvas.ScaleHeight
  162.     dReaC = (m_Xmax - m_Xmin) / (wid - 1)
  163.     dImaC = (m_Ymax - m_Ymin) / (hgt - 1)
  164.     ' Calculate the values.
  165.     ReaC = m_Xmin
  166.     For i = 0 To wid - 1
  167.         ImaC = m_Ymin
  168.         For j = 0 To hgt - 1
  169.             ReaZ = 0
  170.             ImaZ = 0
  171.             ReaZ2 = 0
  172.             ImaZ2 = 0
  173.             clr = 1
  174.             Do While clr < MaxIterations And _
  175.                     ReaZ2 + ImaZ2 < MAX_MAG_SQUARED
  176.                 ' Calculate Z(clr).
  177.                 ReaZ2 = ReaZ * ReaZ
  178.                 ImaZ2 = ImaZ * ImaZ
  179.                 ImaZ = 2 * ImaZ * ReaZ + ImaC
  180.                 ReaZ = ReaZ2 - ImaZ2 + ReaC
  181.                 clr = clr + 1
  182.             Loop
  183.             clr = m_Colors(1 + clr Mod NumColors)
  184.             With pixels(i, j)
  185.                 .rgbRed = clr And &HFF&
  186.                 .rgbGreen = (clr And &HFF00&) \ &H100&
  187.                 .rgbBlue = (clr And &HFF0000) \ &H10000
  188.             End With
  189.             ImaC = ImaC + dImaC
  190.         Next j
  191.         ReaC = ReaC + dReaC
  192.         ' Let the user know we're not dead.
  193.         If i Mod 10 = 0 Then
  194.             picCanvas.Line (0, 0)-(wid, i), vbWhite, BF
  195.             picCanvas.Refresh
  196.         End If
  197.     Next i
  198.     ' Update the image.
  199.     SetBitmapPixels picCanvas, bits_per_pixel, pixels
  200.     picCanvas.Refresh
  201.     picCanvas.Picture = picCanvas.Image
  202.     Caption = "Mand (" & Format$(m_Xmin) & ", " & _
  203.         Format$(m_Ymin) & ")-(" & _
  204.         Format$(m_Xmax) & ", " & _
  205.         Format$(m_Ymax) & ")"
  206. End Sub
  207. ' Reset the number of colors to 0.
  208. Public Sub ResetColors()
  209.     NumColors = 0
  210.     Erase m_Colors
  211. End Sub
  212. ' Start a rubberband box to select a zoom area.
  213. Private Sub picCanvas_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
  214.     m_DrawingBox = True
  215.     m_StartX = X
  216.     m_StartY = Y
  217.     m_CurX = X
  218.     m_CurY = Y
  219.     picCanvas.DrawMode = vbInvert
  220.     picCanvas.Line (m_StartX, m_StartY)-(m_CurX, m_CurY), , B
  221. End Sub
  222. ' Continue the zoom area rubberband box.
  223. Private Sub picCanvas_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
  224.     If Not m_DrawingBox Then Exit Sub
  225.     picCanvas.Line (m_StartX, m_StartY)-(m_CurX, m_CurY), , B
  226.     m_CurX = X
  227.     m_CurY = Y
  228.     picCanvas.Line (m_StartX, m_StartY)-(m_CurX, m_CurY), , B
  229. End Sub
  230. ' Zoom in on the selected area.
  231. Private Sub picCanvas_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
  232. Dim x1 As Single
  233. Dim x2 As Single
  234. Dim y1 As Single
  235. Dim y2 As Single
  236. Dim factor As Single
  237.     If Not m_DrawingBox Then Exit Sub
  238.     m_DrawingBox = False
  239.     picCanvas.Line (m_StartX, m_StartY)-(m_CurX, m_CurY), , B
  240.     picCanvas.DrawMode = vbCopyPen
  241.     m_CurX = X
  242.     m_CurY = Y
  243.     ' Put the coordinates in proper order.
  244.     If m_CurX < m_StartX Then
  245.         x1 = m_CurX
  246.         x2 = m_StartX
  247.     Else
  248.         x1 = m_StartX
  249.         x2 = m_CurX
  250.     End If
  251.     If x1 = x2 Then x2 = x1 + 1
  252.     If m_CurY < m_StartY Then
  253.         y1 = m_CurY
  254.         y2 = m_StartY
  255.     Else
  256.         y1 = m_StartY
  257.         y2 = m_CurY
  258.     End If
  259.     If y1 = y2 Then y2 = y1 + 1
  260.     ' Convert screen coords into drawing coords.
  261.     factor = (m_Xmax - m_Xmin) / picCanvas.ScaleWidth
  262.     m_Xmax = m_Xmin + x2 * factor
  263.     m_Xmin = m_Xmin + x1 * factor
  264.     factor = (m_Ymax - m_Ymin) / picCanvas.ScaleHeight
  265.     m_Ymax = m_Ymin + y2 * factor
  266.     m_Ymin = m_Ymin + y1 * factor
  267.     Screen.MousePointer = vbHourglass
  268.     DrawMandelbrot
  269.     Screen.MousePointer = vbDefault
  270. End Sub
  271. ' Force Visual Basic to resize the bitmap.
  272. Private Sub picCanvas_Resize()
  273.     picCanvas.Cls
  274. End Sub
  275. ' Save the picture.
  276. Private Sub mnuFileSaveAs_Click()
  277. Dim file_name As String
  278.     ' Allow the user to pick a file.
  279.     On Error Resume Next
  280.     dlgFile.DialogTitle = "Save As File"
  281.     dlgFile.Flags = cdlOFNOverwritePrompt + cdlOFNHideReadOnly
  282.     dlgFile.ShowSave
  283.     If Err.Number = cdlCancel Then
  284.         Exit Sub
  285.     ElseIf Err.Number <> 0 Then
  286.         Beep
  287.         MsgBox "Error selecting file.", , vbExclamation
  288.         Exit Sub
  289.     End If
  290.     On Error GoTo 0
  291.     file_name = Trim$(dlgFile.FileName)
  292.     dlgFile.InitDir = Left$(file_name, Len(file_name) _
  293.         - Len(dlgFile.FileTitle) - 1)
  294.     ' Save the picture.
  295.     SavePicture picCanvas.Image, file_name
  296. End Sub
  297. ' Draw the initial Mandelbrot set.
  298. Private Sub Form_Load()
  299. Dim i As Integer
  300.     Me.Show
  301.     DoEvents
  302.     MaxIterations = 64
  303.     ' Create some default colors.
  304.     ResetColors
  305.     AddColor frmConfig.picColor(40).BackColor
  306.     For i = 17 To 23
  307.         AddColor frmConfig.picColor(i).BackColor
  308.     Next i
  309.     Unload frmConfig
  310.     dlgFile.Filter = "Bitmap Files (*.bmp)|*.bmp|" & _
  311.         "All Files (*.*)|*.*"
  312.     dlgFile.InitDir = App.Path
  313.     dlgFile.CancelError = True
  314.     ' Display the first Mandelbrot set.
  315.     mnuScaleFull_Click
  316. End Sub
  317. Private Sub Form_Resize()
  318.     picCanvas.Move 0, 0, ScaleWidth, ScaleHeight
  319. End Sub
  320. ' Let the user set program options.
  321. Private Sub mnuOptOptions_Click()
  322.     frmConfig.Initialize Me
  323.     frmConfig.Show vbModal
  324. End Sub
  325. ' Zoom out to full scale.
  326. Private Sub mnuScaleFull_Click()
  327.     m_Xmin = MIN_X
  328.     m_Xmax = MAX_X
  329.     m_Ymin = MIN_Y
  330.     m_Ymax = MAX_Y
  331.     Screen.MousePointer = vbHourglass
  332.     DrawMandelbrot
  333.     Screen.MousePointer = vbDefault
  334. End Sub
  335. ' Make a series of images.
  336. Private Sub MakeMovie(file_name As String)
  337. Dim num_frames As Integer
  338. Dim frame As Integer
  339. Dim fraction As Single  ' Amount to reduce image.
  340. Dim xmid As Single      ' Center of image.
  341. Dim ymid As Single
  342. Dim wid1 As Single      ' Starting dimensions.
  343. Dim hgt1 As Single
  344. Dim wid2 As Single      ' Finishing dimensions.
  345. Dim hgt2 As Single
  346. Dim wid As Single       ' Current dimensions.
  347. Dim hgt As Single
  348. Dim start_time As Single
  349. Dim stop_time As Single
  350. Dim max_time As Single
  351. Dim min_time As Single
  352. Dim txt As String
  353. Dim value As Integer
  354.     ' See how may frames the user wants.
  355.     txt = InputBox("Number of frames:", _
  356.         "Frames", "20")
  357.     If txt = "" Then Exit Sub
  358.     If IsNumeric(txt) Then num_frames = CInt(txt)
  359.     If num_frames < 1 Then num_frames = 20
  360.     Screen.MousePointer = vbHourglass
  361.     max_time = 0
  362.     min_time = 100000
  363.     ' Set the center of focus and dimensions.
  364.     xmid = (m_Xmin + m_Xmax) / 2
  365.     ymid = (m_Ymin + m_Ymax) / 2
  366.     wid1 = MAX_X - MIN_X
  367.     wid2 = m_Xmax - m_Xmin
  368.     ' Compute start and finish heights.
  369.     hgt1 = wid1 * picCanvas.ScaleHeight / picCanvas.ScaleWidth
  370.     hgt2 = wid2 * picCanvas.ScaleHeight / picCanvas.ScaleWidth
  371.     ' Compute the amount to reduce the image for
  372.     ' each frame.
  373.     fraction = Exp(Log(wid2 / wid1) / (num_frames - 1))
  374.     ' Start cranking out frames.
  375.     wid = wid1
  376.     hgt = hgt1
  377.     For frame = 0 To num_frames - 1
  378.         Caption = "Mand " & Str$(frame) & _
  379.             "/" & Format$(num_frames - 1)
  380.         m_Xmin = xmid - wid / 2
  381.         m_Xmax = xmid + wid / 2
  382.         m_Ymin = ymid - hgt / 2
  383.         m_Ymax = ymid + hgt / 2
  384.         start_time = Timer
  385.         DrawMandelbrot
  386.         stop_time = Timer
  387.         If min_time > stop_time - start_time Then min_time = stop_time - start_time
  388.         If max_time < stop_time - start_time Then max_time = stop_time - start_time
  389.         SavePicture picCanvas.Image, _
  390.             file_name & Format$(frame) & ".bmp"
  391.         Beep
  392.         DoEvents
  393.         wid = wid * fraction
  394.         hgt = hgt * fraction
  395.     Next frame
  396.     Screen.MousePointer = vbDefault
  397.     MsgBox _
  398.         "Longest:  " & Format$(max_time, "0.00") & _
  399.             " seconds." & vbCrLf & _
  400.         "Shortest: " & Format$(min_time, "0.00") & _
  401.             " seconds." & vbCrLf
  402. End Sub
  403. ' Make a series of images.
  404. Private Sub mnuMovieCreate_Click()
  405. Dim old_file_name As String
  406. Dim file_name As String
  407. Dim pos As Integer
  408.     ' Allow the user to pick a file.
  409.     On Error Resume Next
  410.     old_file_name = dlgFile.FileName
  411.     dlgFile.DialogTitle = "Select base file name (no number)"
  412.     dlgFile.Flags = cdlOFNOverwritePrompt + cdlOFNHideReadOnly
  413.     pos = InStr(old_file_name, ".")
  414.     If pos > 0 Then old_file_name = Left$(old_file_name, pos - 1)
  415.     dlgFile.FileName = old_file_name
  416.     dlgFile.ShowSave
  417.     If Err.Number = cdlCancel Then
  418.         dlgFile.FileName = old_file_name
  419.         Exit Sub
  420.     ElseIf Err.Number <> 0 Then
  421.         dlgFile.FileName = old_file_name
  422.         MsgBox "Error selecting file.", , vbExclamation
  423.         Exit Sub
  424.     End If
  425.     On Error GoTo 0
  426.     file_name = Trim$(dlgFile.FileName)
  427.     dlgFile.FileName = old_file_name
  428.     dlgFile.InitDir = Left$(file_name, Len(file_name) _
  429.         - Len(dlgFile.FileTitle) - 1)
  430.     ' Trim off the extension if any.
  431.     pos = InStr(file_name, ".")
  432.     If pos > 0 Then file_name = Left$(file_name, pos - 1)
  433.     ' Add a trailing underscore if needed.
  434.     If Right$(file_name, 1) <> "_" Then _
  435.         file_name = file_name & "_"
  436.     ' Make the movie.
  437.     MakeMovie file_name
  438. End Sub
  439. ' Increase the area shown by a factor of Index.
  440. Private Sub mnuScale_Click(Index As Integer)
  441. Dim size As Single
  442. Dim mid As Single
  443.     size = Index * (m_Xmax - m_Xmin)
  444.     If size > 3.2 Then
  445.         mnuScaleFull_Click
  446.         Exit Sub
  447.     End If
  448.     mid = (m_Xmin + m_Xmax) / 2
  449.     m_Xmin = mid - size / 2
  450.     m_Xmax = mid + size / 2
  451.     size = Index * (m_Ymax - m_Ymin)
  452.     If size > 2.4 Then
  453.         mnuScaleFull_Click
  454.         Exit Sub
  455.     End If
  456.     mid = (m_Ymin + m_Ymax) / 2
  457.     m_Ymin = mid - size / 2
  458.     m_Ymax = mid + size / 2
  459.     Screen.MousePointer = vbHourglass
  460.     DrawMandelbrot
  461.     Screen.MousePointer = vbDefault
  462. End Sub
  463.